package mudclient;	

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.NotYetConnectedException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

import javax.swing.JOptionPane;
import javax.swing.JTextArea;

public class TelnetThread extends Thread {
	
	public TelnetThread(String hostname, int port, MudClientTextPane itp, JTextArea ota) {
		super();
		
		this.hostname = hostname;
		this.port = port;
		
		this.itp = itp;
		this.ita = ota;
		r = new ReadProcessingThread(itp);
		
		this.ita = ota;
	}
	
    public void run() {
    	Selector selector = null;
    	
    	try {
    		selector = Selector.open();
    	} catch(IOException e) { 
    	}
    	final ByteBuffer bb = ByteBuffer.allocateDirect(2048);
    	
    	try {
    		mudSocket = SocketChannel.open();
    		mudSocket.configureBlocking(false);
    		mudSocket.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ);
    		mudSocket.connect(new InetSocketAddress(hostname, port));
    	} catch(IOException e) {
    	}
    	
    	while(running) {
    		try {
    			selector.select();
    			
    			Iterator<SelectionKey> i = ((Set<SelectionKey>) selector.selectedKeys()).iterator();
    			if(i.hasNext()) {
    				SelectionKey key = i.next();
    				i.remove();
	    			
	    			if(key.isConnectable()) {
	    				mudSocket.finishConnect();
	    				mudSocket.register(selector, SelectionKey.OP_READ);
	    		    	ita.addKeyListener(new KeyAdapter() {
	    		    		public void keyPressed(KeyEvent e) {
	    		    			if (e.getKeyCode() == KeyEvent.VK_ENTER) {
	    		    				e.consume();
	    		    				try {
	    		    					itp.appendString(ita.getText() + "\n", "defaultOutput");
	    		    					ita.select(0, ita.getText().length());
	    		    					mudSocket.write(ByteBuffer.wrap((ita.getText() + "\n").getBytes()));
	    		    				} catch(NotYetConnectedException ex) {
	    		    					JOptionPane.showMessageDialog(MudClientApplication.getMainFrame(), "mud output not yet connected exception");
	    		    				} catch(ClosedByInterruptException ex) {
	    		    					JOptionPane.showMessageDialog(MudClientApplication.getMainFrame(), "mud output closedbyinterrupt");
	    		    				} catch(AsynchronousCloseException ex) {
	    		    					JOptionPane.showMessageDialog(MudClientApplication.getMainFrame(), "mud output async close");
	    		    				} catch(ClosedChannelException ex) {
	    		    					JOptionPane.showMessageDialog(MudClientApplication.getMainFrame(), "mud output closed channel");
	    		    				} catch(IOException ex) { 
	    		    					JOptionPane.showMessageDialog(MudClientApplication.getMainFrame(), "mud output ioexception");
	    		    				}
	    		    			}
	    		    		}
	    		    	});
	    		    	r.start();
	    			}
	    			else if (key.isReadable()) {
	    				int a = mudSocket.read(bb);
	    				if(a == -1) {
	    					JOptionPane.showMessageDialog(MudClientApplication.getMainFrame(), "Connection lost!");
	    					mudSocket.close();
	    					running = false;
	    				} else {
	    					bb.flip();
	    					byte[] b = new byte[bb.limit()];
	    					bb.get(b);
	    					r.addText(b);
	    					bb.clear();
	    				}
	    			}
	    		}
    		} catch(IOException e) {
    			
    		} catch(CancelledKeyException e) {
    			
    		}
        	if(running == false) {
        		try {
        			mudSocket.close();
        		} catch(IOException e) { 
        			
        		}
        	}
   		}
    }
    
    public synchronized void setRunning(boolean b) {
    	running = b;
    }
    
    
    
    private volatile boolean running = true;
    private ReadProcessingThread r;
    private SocketChannel mudSocket;
    private JTextArea ita;
    private MudClientTextPane itp;
    private String hostname;
    private int port;
    
    
    
}